home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / MacApp Release 10 / MacApp Release 10 - HD Ready / Libraries / Framework / Sources / UMacAppUtilities.cp < prev    next >
Encoding:
Text File  |  1996-04-03  |  53.5 KB  |  1,866 lines  |  [TEXT/MPS ]

  1. //----------------------------------------------------------------------------------------
  2. // UMacAppUtilities.cp
  3. // Copyright © 1984-96 by Apple Computer, Inc. All rights reserved.
  4. //----------------------------------------------------------------------------------------
  5.  
  6. #ifndef __UMACAPPUTILITIES__
  7. #include "UMacAppUtilities.h"
  8. #endif
  9.  
  10. // MacApp
  11.  
  12. #ifndef __MACAPPVERSION__
  13. #include "MacAppVersion.h"
  14. #endif
  15.  
  16. #ifndef __UDEBUG__
  17. #include "UDebug.h"
  18. #endif
  19.  
  20. #ifndef __UDISPATCHER__
  21. #include "UDispatcher.h"
  22. #endif
  23.  
  24. #ifndef __UGEOMETRY__
  25. #include "UGeometry.h"
  26. #endif
  27.  
  28. #ifndef __UMACAPPGLOBALS__
  29. #include "UMacAppGlobals.h"
  30. #endif
  31.  
  32. #ifndef __UMEMORY__
  33. #include "UMemory.h"
  34. #endif
  35.  
  36. #ifndef __UNIVERSALSTARTUP__
  37. #include "UniversalStartup.h"
  38. #endif
  39.  
  40. #ifndef __USTREAM__
  41. #include "UStream.h"
  42. #endif
  43.  
  44. #ifndef __UWINDOW__
  45. #include "UWindow.h"
  46. #endif
  47.  
  48. // OpenDoc
  49.  
  50. #if qOpenDoc
  51. #ifndef SOM_ODPart_xh
  52. #include "Part.xh"
  53. #endif
  54.  
  55. #endif
  56.  
  57. // Toolbox
  58.  
  59. #ifndef __DEVICES__
  60. #include <Devices.h>
  61. #endif
  62.  
  63. #ifndef __DIALOGS__
  64. #include <Dialogs.h>
  65. #endif
  66.  
  67. #ifndef __ERRORS__
  68. #include <Errors.h>
  69. #endif
  70.  
  71. #ifndef __FONTS__
  72. #include <Fonts.h>
  73. #endif
  74.  
  75. #if qPowerPC || qModelCFM
  76. #ifndef __FRAGLOAD__
  77. #include <FragLoad.h>
  78. #endif
  79.  
  80. #endif
  81.  
  82. #ifndef __GESTALT__
  83. #include <Gestalt.h>
  84. #endif
  85.  
  86. #ifndef __LOWMEM__
  87. #include <LowMem.h>
  88. #endif
  89.  
  90. #ifndef __MEMORY__
  91. #include <Memory.h>
  92. #endif
  93.  
  94. #ifndef __MENUS__
  95. #include <Menus.h>
  96. #endif
  97.  
  98. #ifndef __OSEVENTS__
  99. #include <OSEvents.h>
  100. #endif
  101.  
  102. #ifndef __PACKAGES__
  103. #include <Packages.h>
  104. #endif
  105.  
  106. #ifndef __RESOURCES__
  107. #include <Resources.h>
  108. #endif
  109.  
  110. #ifndef __SCRAP__
  111. #include <Scrap.h>
  112. #endif
  113.  
  114. #ifndef __SCRIPT__
  115. #include <Script.h>
  116. #endif
  117.  
  118. #ifndef __TEXTUTILS__
  119. #include <TextUtils.h>
  120. #endif
  121.  
  122. #if qNeedsThreads
  123. #ifndef __THREADS__
  124. #include <Threads.h>
  125. #endif
  126.  
  127. #endif
  128.  
  129. #ifndef __TOOLUTILS__
  130. #include <ToolUtils.h>
  131. #endif
  132.  
  133. #ifndef __TRAPS__
  134. #include <Traps.h>
  135. #endif
  136.  
  137. // ANSI
  138.  
  139. #ifndef __STDIO__
  140. #include <stdio.h>
  141. #endif
  142.  
  143. //----------------------------------------------------------------------------------------
  144. // extern definitions:
  145. extern WindowRef gWorkPort;
  146.  
  147. // constants
  148.  
  149. #if qOldConfigurationFlags
  150. Configuration gConfiguration;
  151. #endif
  152.  
  153. #if qDebugMsg
  154. const CStr15 gBoolString[2] = { "false", "true"};
  155. #endif
  156.  
  157. Boolean gUDialogInitialized;
  158. Boolean gUGridViewInitialized;
  159. Boolean gUPrintingInitialized;
  160. Boolean gUTEViewInitialized;
  161.  
  162. TEHandle gMATextBoxTE;
  163. WordBreakUPP gTEDefaultWordBreak;
  164. const VHSelect gOrthogonal[2] = { hSel, vSel};
  165.  
  166. const CRect gZeroRect(0, 0, 0, 0);
  167. const CPoint gZeroPt(0, 0);
  168. const VPoint gZeroVPt(0, 0);
  169. const VRect gZeroVRect(0, 0, 0, 0);
  170.  
  171. const CPoint kBestSystemLocation(-1, -1);
  172.  
  173. const CStr2 gEmptyString(""); // Constructor keeps this from getting dead-stripped
  174.  
  175. // the primary colors 
  176. const CRGBColor gRGBBlack(0, 0, 0);
  177. const CRGBColor gRGBWhite(0xFFFF, 0xFFFF, 0xFFFF);
  178. const CRGBColor gRGBRed(0xFFFF, 0, 0);
  179. const CRGBColor gRGBGreen(0, 0xFFFF, 0);
  180. const CRGBColor gRGBBlue(0, 0, 0xFFFF);
  181.  
  182.  
  183. //========================================================================================
  184. // GLOBAL Procedures
  185. //========================================================================================
  186. static pascal void StdNoRect(GrafVerb            /* verb */,
  187.                              const CRect&        /* r */ );
  188. static void InitMyPrivateTE(const CRect& box,
  189.                             short heapSize);
  190. static void CheckAdornment(CntlAdornment p,
  191.                            CntlAdornment alias,
  192.                            CStr255 theString,
  193.                            char* name);
  194. static void CheckStyleItem(unsigned char s,
  195.                            unsigned char alias,
  196.                            CStr255 theString,
  197.                            char* name);
  198.  
  199. //========================================================================================
  200. // CLASS CWhileOutlinePreferred
  201. //========================================================================================
  202. #undef Inherited
  203.  
  204. //----------------------------------------------------------------------------------------
  205. // CWhileOutlinePreferred::CWhileOutlinePreferred: 
  206. //----------------------------------------------------------------------------------------
  207. #pragma segment MAUtilitiesRes
  208.  
  209. CWhileOutlinePreferred::CWhileOutlinePreferred(Boolean preferOutline)
  210. {
  211.     // initialize data members
  212.     fPreferOutline = preferOutline;
  213.     fOutlinePreferredChanged = FALSE;
  214.  
  215.     // change outline preferred, if necessary
  216.     if (HasTrueType())
  217.     {
  218.         fOutlinePreferredChanged = (GetOutlinePreferred() != fPreferOutline);
  219.         if (fOutlinePreferredChanged)
  220.             SetOutlinePreferred(fPreferOutline);
  221.     }
  222. }
  223.  
  224. //----------------------------------------------------------------------------------------
  225. // CWhileOutlinePreferred::~CWhileOutlinePreferred: 
  226. //----------------------------------------------------------------------------------------
  227. #pragma segment MAUtilitiesRes
  228.  
  229. CWhileOutlinePreferred::~CWhileOutlinePreferred()
  230. {
  231.     // restore outline preferred, if necessary
  232.     if (HasTrueType() && fOutlinePreferredChanged)
  233.         SetOutlinePreferred(!fPreferOutline);
  234. }
  235.  
  236.  
  237. //========================================================================================
  238. // CLASS CStringListRsrc
  239. //========================================================================================
  240. #undef Inherited
  241.  
  242. //----------------------------------------------------------------------------------------
  243. // CStringListRsrc::GetString: 
  244. //----------------------------------------------------------------------------------------
  245. #pragma segment MAUtilitiesRes
  246.  
  247. void CStringListRsrc::GetString(short index,
  248.                                 CStr255& theString) const
  249. {
  250.     if (fStrListID != kNoResource)
  251.         GetIndString(theString, fStrListID, index);
  252. }
  253.  
  254. //----------------------------------------------------------------------------------------
  255. // CStringListRsrc::FindString: 
  256. //----------------------------------------------------------------------------------------
  257. #pragma segment MAUtilitiesRes
  258.  
  259. short CStringListRsrc::FindString(const CStr255& theString,
  260.                                   Boolean addString)
  261. {
  262.     short numStrings = CountStrings();
  263.  
  264.     for (short i = 1; i <= numStrings; ++i)
  265.     {
  266.         CStr255 testString;
  267.         GetString(i, testString);
  268.  
  269.         if (testString == theString)
  270.             return i;                            // found it! return the index
  271.     }
  272.  
  273.     // CString is not found, should we add it?
  274.     if (addString == kAddString)
  275.         return AppendString(theString);    // added it! return the index
  276.  
  277.     // CString not found...sigh!
  278.     return kNoResource;
  279. }
  280.  
  281. //----------------------------------------------------------------------------------------
  282. // CStringListRsrc::AppendString: 
  283. //----------------------------------------------------------------------------------------
  284. #pragma segment MAUtilitiesRes
  285.  
  286. short CStringListRsrc::AppendString(const CStr255& theString)
  287. {
  288.     short returnVal = kNoResource;
  289.  
  290.     short totalStringLength = theString.Length() + kLengthByte;
  291.     Handle aHandle = GetResource('STR#', fStrListID);
  292.     if (aHandle)
  293.     {
  294.         Size itsSize = GetHandleSize(aHandle);
  295.         if (itsSize > 0)
  296.         {
  297.             short numStrings = CountStrings();
  298.             SetPermHandleSize(aHandle, itsSize + totalStringLength);
  299.             (**((IntegerHandle)aHandle)) =++numStrings;// increment the count of strings in the STR# resource
  300.  
  301.             // needs a failure handler
  302.             long result = Munger(aHandle, itsSize, NULL, totalStringLength, &theString, totalStringLength);
  303.             if (result > 0)
  304.             {
  305.                 // mark it as changed
  306.                 ChangedResource(aHandle);
  307.  
  308.                 returnVal = numStrings;
  309.             }
  310.         }
  311.     }
  312.     else
  313.     {
  314.         // must create the resource...
  315.         aHandle = NewPermHandle(sizeof(short) + totalStringLength);
  316.         (**((IntegerHandle)aHandle)) = 1;        // set the count of strings in the STR# resource
  317.         long result = Munger(aHandle, sizeof(short), NULL, totalStringLength, &theString, totalStringLength);
  318.         if (result > 0)
  319.         {
  320.             AddResource(aHandle, 'STR#', fStrListID, fStrListRsrcName);
  321.             FailResError();                        // if fails, it's most likely because the file is read-only
  322.  
  323.             SetResAttrs(aHandle, resPurgeable);
  324.  
  325.             // Need the following ChangedResource call because the SetResAttrs call on the previous
  326.             // line cleared the "resChanged" attribute of the resource.
  327.             ChangedResource(aHandle);
  328.  
  329.             returnVal = 1;
  330.         }
  331.     }
  332.  
  333.     return returnVal;
  334. }
  335.  
  336. //----------------------------------------------------------------------------------------
  337. // CStringListRsrc::ClearAll: 
  338. //----------------------------------------------------------------------------------------
  339. #pragma segment MAUtilitiesRes
  340.  
  341. void CStringListRsrc::ClearAll()
  342. {
  343.     Handle aHandle = GetResource('STR#', fStrListID);
  344.     if (aHandle)
  345.     {
  346.         SetPermHandleSize(aHandle, sizeof(short));
  347.         (**((IntegerHandle)aHandle)) = 0;        // set the count of strings in the STR# resource
  348.  
  349.         // mark it as changed
  350.         ChangedResource(aHandle);
  351.     }
  352. }
  353.  
  354. //----------------------------------------------------------------------------------------
  355. // CStringListRsrc::CountStrings: 
  356. //----------------------------------------------------------------------------------------
  357. #pragma segment MAUtilitiesRes
  358.  
  359. short CStringListRsrc::CountStrings() const
  360. {
  361.     // return the leading integer in the STR# resource:
  362.     //
  363.     // type 'STR#' {
  364.     //      integer = $$Countof(StringArray);
  365.     //      array StringArray {
  366.     //              pstring;
  367.     //      };
  368.     // };
  369.  
  370.     Handle aHandle = GetResource('STR#', fStrListID);
  371.  
  372.     return aHandle ? **((IntegerHandle)aHandle) : kNoResource;
  373. }
  374.  
  375. //----------------------------------------------------------------------------------------
  376. // CStringListRsrc::GetListName: 
  377. //----------------------------------------------------------------------------------------
  378. #pragma segment MARes
  379.  
  380. void CStringListRsrc::GetListName(CStr255& theString)
  381. {
  382.     // Do we have the name in our field?
  383.     if (fStrListRsrcName.Length() > 0)
  384.         theString = fStrListRsrcName;
  385.     else                                        //    We don't have the name so try and get it from the resource
  386.         {
  387.             // Get the resource's handle
  388.             Handle aHandle = GetResource('STR#', fStrListID);
  389.             if (aHandle)
  390.             {
  391.                 short itsRsrcID;
  392.                 CStr255 itsName;
  393.                 ResType itsType;
  394.  
  395.                 // Extract the resource info from the handle
  396.                 GetResInfo(aHandle, &itsRsrcID, &itsType, itsName);
  397.                 if (itsName.Length() > 0)
  398.                 {
  399.                     theString = itsName;
  400.  
  401.                     // Store the name in our field
  402.                     fStrListRsrcName = theString;
  403.                 }
  404.  
  405.                 ReleaseResource(aHandle);
  406.             }
  407.             else                                // Sorry we don't have anything so return an empty CString
  408.                 theString.Empty();
  409.         }
  410. }
  411.  
  412. //----------------------------------------------------------------------------------------
  413. // CStringListRsrc::RemoveAt: 
  414. //----------------------------------------------------------------------------------------
  415. #pragma segment MAUtilitiesRes
  416.  
  417. void CStringListRsrc::RemoveAt(short index)
  418. {
  419.     if ((index > 0) && (index <= CountStrings()))
  420.     {
  421.         Handle aHandle = GetResource('STR#', fStrListID);
  422.         if (aHandle)
  423.         {
  424.             Size originalSize = GetHandleSize(aHandle);
  425.  
  426.             // determine the accumulated size
  427.             Size accumulatedSize = sizeof(short);// the accumulated size is the size of the count
  428.             for (short i = 1; i < index; ++i)
  429.                 accumulatedSize += (*((CStringPtr)(*aHandle + accumulatedSize))).Length() + kLengthByte;
  430.  
  431.             // determine the actual CString size
  432.             Size stringSize = (*((CStringPtr)(*aHandle + accumulatedSize))).Length() + kLengthByte;
  433.  
  434.             // move the the data in the handle
  435.             MABlockMove(*aHandle + accumulatedSize + stringSize, *aHandle + accumulatedSize, originalSize - accumulatedSize - stringSize);
  436.  
  437.             // trim the handle down to its new size
  438.             SetPermHandleSize(aHandle, originalSize - stringSize);
  439.  
  440.             // decrement count of strings in STR# resource
  441.             --(**((IntegerHandle)aHandle));
  442.  
  443.             // mark it as changed
  444.             ChangedResource(aHandle);
  445.         }
  446. #if qDebugMsg
  447.         else
  448.             fprintf(stderr, "CStringListRsrc::RemoveAt can't find STR# = %d.\n", fStrListID);
  449. #endif
  450.  
  451.     }
  452. #if qDebugMsg
  453.     else
  454.         fprintf(stderr, "CStringListRsrc::RemoveAt there's no CString at %d to remove!\n", index);
  455. #endif
  456. }
  457.  
  458. //----------------------------------------------------------------------------------------
  459. // CStringListRsrc::ReplaceAt: 
  460. //----------------------------------------------------------------------------------------
  461. #pragma segment MAUtilitiesRes
  462.  
  463. void CStringListRsrc::ReplaceAt(const CStr255& theString,
  464.                                 short index)
  465. {
  466.     if ((index > 0) && (index <= CountStrings()))
  467.     {
  468.         Handle aHandle = GetResource('STR#', fStrListID);
  469.         if (aHandle)
  470.         {
  471.             Size newStringSize = theString.Length() + kLengthByte;// the actual CString size
  472.             Size originalSize = GetHandleSize(aHandle);
  473.  
  474.             // determine the accumulated size of the valid portion of the resource
  475.             Size accumulatedSize = sizeof(short);// the accumulated size is the size of the count
  476.             for (short i = 1; i < index; ++i)
  477.                 accumulatedSize += (*((CStringPtr)(*aHandle + accumulatedSize))).Length() + kLengthByte;
  478.  
  479.             // determine the actual CString size
  480.             Size oldStringSize = (*((CStringPtr)(*aHandle + accumulatedSize))).Length() + kLengthByte;
  481.  
  482.             // determine the new handle size
  483.             Size newHandleSize = originalSize + (newStringSize - oldStringSize);
  484.  
  485.             // determine whether to grow or shrink the handle?
  486.             if (newStringSize > oldStringSize)
  487.             {
  488.                 // grow the handle
  489.                 SetPermHandleSize(aHandle, newHandleSize);
  490.  
  491.                 // move the bytes
  492.                 MABlockMove(*aHandle + accumulatedSize + oldStringSize, *aHandle + accumulatedSize + newStringSize, originalSize - accumulatedSize - oldStringSize);
  493.             }
  494.             else if (oldStringSize > newStringSize)
  495.             {
  496.                 // move the bytes
  497.                 MABlockMove(*aHandle + accumulatedSize + oldStringSize, *aHandle + accumulatedSize + newStringSize, originalSize - accumulatedSize - oldStringSize);
  498.  
  499.                 // shrink the handle
  500.                 SetPermHandleSize(aHandle, newHandleSize);
  501.             }
  502.  
  503.             // assign the CString
  504.             *((CStr255 *)(*aHandle + accumulatedSize)) = theString;
  505.  
  506.             // mark it as changed
  507.             ChangedResource(aHandle);
  508.         }
  509. #if qDebugMsg
  510.         else
  511.             fprintf(stderr, "CStringListRsrc::ReplaceAt can't find STR# = %d.\n", fStrListID);
  512. #endif
  513.  
  514.     }
  515. #if qDebugMsg
  516.     else
  517.         fprintf(stderr, "CStringListRsrc::ReplaceAt there's no CString at %d to replace!\n", index);
  518. #endif
  519. }
  520.  
  521.  
  522. //========================================================================================
  523. // CLASS CWMgrIterator
  524. //========================================================================================
  525. #undef Inherited
  526. #define Inherited CIterator
  527.  
  528. //----------------------------------------------------------------------------------------
  529. // CWMgrIterator::CWMgrIterator: 
  530. //----------------------------------------------------------------------------------------
  531. #pragma segment MAUtilitiesRes
  532.  
  533. CWMgrIterator::CWMgrIterator(Boolean itsForward) :
  534.     fIterateForward(itsForward)
  535. {
  536.     Reset();
  537. }
  538.  
  539. //----------------------------------------------------------------------------------------
  540. // CWMgrIterator::Reset: 
  541. //----------------------------------------------------------------------------------------
  542. #pragma segment MAUtilitiesRes
  543.  
  544. void CWMgrIterator::Reset()
  545. {
  546.     fCurrentWindow = fIterateForward ? FirstWindow() : LastWindow();
  547. }
  548.  
  549. //----------------------------------------------------------------------------------------
  550. // CWMgrIterator::MAUtilitiesRes: 
  551. //----------------------------------------------------------------------------------------
  552. #pragma segment MAUtilitiesRes
  553.  
  554. WindowRef CWMgrIterator::FirstWMgrWindow()
  555. {
  556.     Reset();
  557.  
  558.     return fCurrentWindow;                        // Always return the first window
  559. }
  560.  
  561. //----------------------------------------------------------------------------------------
  562. // CWMgrIterator::NextWMgrWindow: 
  563. //----------------------------------------------------------------------------------------
  564. #pragma segment MAUtilitiesRes
  565.  
  566. WindowRef CWMgrIterator::NextWMgrWindow()
  567. {
  568.     Advance();
  569.  
  570.     return fCurrentWindow;
  571. }
  572.  
  573. //----------------------------------------------------------------------------------------
  574. // CWMgrIterator::Advance: 
  575. //----------------------------------------------------------------------------------------
  576. #pragma segment MAUtilitiesRes
  577.  
  578. void CWMgrIterator::Advance()
  579. {
  580.     if (fCurrentWindow)
  581.         fCurrentWindow = fIterateForward ? NextWindow(fCurrentWindow) : PreviousWindow(fCurrentWindow);
  582. }
  583.  
  584. //----------------------------------------------------------------------------------------
  585. // CWMgrIterator::FirstWindow: 
  586. //----------------------------------------------------------------------------------------
  587. #pragma segment MAUtilitiesRes
  588. WindowRef CWMgrIterator::FirstWindow()
  589. {
  590.     WindowRef currentWindow = (WindowRef)LMGetWindowList();
  591.     if (currentWindow && (currentWindow == gWorkPort))
  592.         currentWindow = NextWindow(currentWindow);
  593.  
  594.     return currentWindow;
  595. }
  596.  
  597. //----------------------------------------------------------------------------------------
  598. // CWMgrIterator::NextWindow: 
  599. //----------------------------------------------------------------------------------------
  600. #pragma segment MAUtilitiesRes
  601. WindowRef CWMgrIterator::NextWindow(WindowRef aWindow)
  602. {
  603.     WindowRef currentWindow = GetNextWindow(aWindow);
  604.  
  605.     while (currentWindow && (currentWindow == gWorkPort))
  606.         // ignore the work window
  607.         currentWindow = GetNextWindow(currentWindow);
  608.  
  609.     return currentWindow;
  610. }
  611.  
  612. //----------------------------------------------------------------------------------------
  613. // CWMgrIterator::PreviousWindow: 
  614. //----------------------------------------------------------------------------------------
  615. #pragma segment MAUtilitiesRes
  616. WindowRef CWMgrIterator::PreviousWindow(WindowRef aWindow)
  617. {
  618.     WindowRef currentWindow = FirstWindow();
  619.     while (currentWindow && (NextWindow(currentWindow) != aWindow))
  620.         currentWindow = NextWindow(currentWindow);
  621.  
  622.     return currentWindow;
  623. }
  624.  
  625.  
  626. //----------------------------------------------------------------------------------------
  627. // CWMgrIterator::LastWindow: 
  628. //----------------------------------------------------------------------------------------
  629. #pragma segment MAUtilitiesRes
  630. WindowRef CWMgrIterator::LastWindow()
  631. {
  632.     WindowRef currentWindow = FirstWindow();
  633.     while (currentWindow && NextWindow(currentWindow))
  634.         currentWindow = NextWindow(currentWindow);
  635.  
  636.     return currentWindow;
  637. }
  638.  
  639.  
  640. //========================================================================================
  641. // GLOBAL Procedures
  642. //========================================================================================
  643. #undef Inherited
  644.  
  645. //----------------------------------------------------------------------------------------
  646. // CanWriteLn: 
  647. //----------------------------------------------------------------------------------------
  648. #pragma segment MAUtilitiesRes
  649.  
  650. #if qDebug
  651. Boolean CanWriteLn()
  652. {
  653.     return DebugCanWriteLn();
  654. }
  655. #endif
  656.  
  657. //----------------------------------------------------------------------------------------
  658. // CanReadLn: 
  659. //----------------------------------------------------------------------------------------
  660. #pragma segment MAUtilitiesRes
  661.  
  662. #if qDebug
  663. Boolean CanReadLn()
  664. {
  665.     return DebugCanReadLn();
  666. }
  667. #endif
  668.  
  669. //----------------------------------------------------------------------------------------
  670. // CenterRectOnScreen: 
  671. //----------------------------------------------------------------------------------------
  672. // This must always be in a resident segment as aRect may be within a handle
  673. #pragma segment MAUtilitiesRes
  674.  
  675. void CenterRectOnScreen(CRect& aRect,
  676.                         Boolean horizontally,
  677.                         Boolean vertically,
  678.                         Boolean forDialog)
  679. {
  680.     short newSize = 0;
  681.     CPoint rectSize(aRect.GetSize());
  682.  
  683.     CPoint screenSize(((CRect &)qd.screenBits.bounds).GetSize());
  684.     screenSize.v -= GetMBarHeight();
  685.  
  686.     // Calculate screen size minus menu bar 
  687.     if (horizontally)
  688.         aRect.left = (screenSize.h - rectSize.h) / 2;
  689.     if (vertically)
  690.         if (forDialog)
  691.         {
  692.             newSize = (screenSize.v - rectSize.v) / 5;
  693.             aRect.top = (short)(Max(newSize, 10) + GetMBarHeight());
  694.         }
  695.         else
  696.             aRect.top = (screenSize.v - rectSize.v) / 2;
  697.  
  698.     aRect[botRight] = aRect[topLeft] + rectSize;
  699. }
  700.  
  701. //----------------------------------------------------------------------------------------
  702. // ConcatNumber: 
  703. //----------------------------------------------------------------------------------------
  704. #pragma segment MAUtilitiesRes
  705.  
  706. void ConcatNumber(const CStr255& aString,
  707.                   long aNumber,
  708.                   CStr255& theResult)
  709. {
  710.     NumToString(aNumber, theResult);
  711.     theResult = aString + theResult;
  712. }
  713.  
  714. //----------------------------------------------------------------------------------------
  715. // PullApplicationToFront: 
  716. //----------------------------------------------------------------------------------------
  717. // Must be in main segment as it is called in early initialization && in MacAppAlert
  718. #pragma segment Main
  719.  
  720. void PullApplicationToFront()
  721. {
  722.     EventRecord theEvent;
  723.  
  724.     // The "Programmer's guide to MultiFinder says make an event call several times. I
  725.     // guess 3 calls counts as several. Also, it says call GetNextEvent but we don't want
  726.     // to lose events on the floor so we use EventAvail since it seems to work OK
  727.     for (short i = 1; i <= 3; ++i)
  728.         EventAvail(everyEvent, &theEvent);
  729. }
  730.  
  731. //----------------------------------------------------------------------------------------
  732. // MAInteractWithUser: 
  733. //----------------------------------------------------------------------------------------
  734. #pragma segment MAUtilitiesRes
  735.  
  736. OSErr MAInteractWithUser(long timeOutInTicks,
  737.                          NMRecPtr nmReqPtr,
  738.                          AEIdleUPP idleProc)
  739. {
  740.     return gDispatcher->InteractWithUser(timeOutInTicks, nmReqPtr, idleProc);
  741. }
  742.  
  743. //----------------------------------------------------------------------------------------
  744. // MAInteractWithUser: 
  745. //----------------------------------------------------------------------------------------
  746. #pragma segment MAUtilitiesRes
  747.  
  748. OSErr MAInteractWithUser()
  749. {
  750.     return gDispatcher->InteractWithUser(kMacAppTimeout, gNotificationPtr, TAppleEvent::fgIdleProc);
  751. }
  752.  
  753. //----------------------------------------------------------------------------------------
  754. // MAInteractWithUserNoIdleProc: 
  755. //----------------------------------------------------------------------------------------
  756. #pragma segment MAUtilitiesRes
  757.  
  758. OSErr MAInteractWithUserNoIdleProc()
  759. {
  760.     return gDispatcher->InteractWithUser(kMacAppTimeout, gNotificationPtr, NULL);
  761. }
  762.  
  763. #if !qNeedsSystem7_5
  764. //----------------------------------------------------------------------------------------
  765. // MACharacterByteType: 
  766. //----------------------------------------------------------------------------------------
  767. #pragma segment MAUtilitiesRes
  768. short MACharacterByteType(Ptr textBuf,
  769.                           short textOffset,
  770.                           ScriptCode script)
  771. {
  772.     // CharacterByteType only avail in sys 7.1+
  773.     short byteType;
  774.     if (GetSystemVersion() >= 0x0710)
  775.         byteType = CharacterByteType(textBuf, textOffset, script);// textOffset is zero-based 
  776.     else
  777.     {
  778.         short oldScript = SetKeyScript(script);
  779.         byteType = CharByte(textBuf, textOffset);// textOffset is zero-based 
  780.         SetKeyScript(oldScript);
  781.     }
  782.  
  783. #if qDebug
  784.     Assertion(byteType != smMiddleByte, "\pbyteType != smMiddleByte. We should never receive smMiddleByte");
  785. #endif
  786.  
  787.     return byteType;
  788. }
  789.  
  790. //----------------------------------------------------------------------------------------
  791. // MACharacterByte: 
  792. //----------------------------------------------------------------------------------------
  793. #pragma segment MAUtilitiesRes
  794. short MACharacterType(Ptr textBuf,
  795.                       short textOffset,
  796.                       ScriptCode script)
  797. {
  798.     // CharacterType only avail in sys 7.1+
  799.     short byteType;
  800.     if (GetSystemVersion() >= 0x0710)
  801.         byteType = CharacterType(textBuf, textOffset, script);// textOffset is zero-based 
  802.     else
  803.     {
  804.         short oldScript = SetKeyScript(script);
  805.         byteType = CharType(textBuf, textOffset);// textOffset is zero-based 
  806.         SetKeyScript(oldScript);
  807.     }
  808.  
  809. #if qDebug
  810.     Assertion(byteType != smMiddleByte, "\pbyteType != smMiddleByte. We should never receive smMiddleByte");
  811. #endif
  812.  
  813.     return byteType;
  814. }
  815. #endif
  816.  
  817. //----------------------------------------------------------------------------------------
  818. // CompareMultiByteChars: 
  819. //----------------------------------------------------------------------------------------
  820. #pragma segment MAUtilitiesRes
  821.  
  822. Boolean CompareMultiByteChars(const CStr31& first,
  823.                               const CStr31& second,
  824.                               Boolean caseSens)
  825. {
  826.     Boolean areEqual = FALSE;
  827.  
  828.     if (caseSens)
  829.         areEqual = first == second;
  830.     else
  831.     {
  832.         short textOffset = 0;
  833.         Boolean done = FALSE;
  834.  
  835.         do
  836.         {
  837.             ++textOffset;
  838.             char c = first[textOffset];
  839.  
  840.             short byteType = MACharacterByteType((Ptr) & c, 0, smCurrentScript);
  841.  
  842.             areEqual = first[textOffset] == second[textOffset];
  843.             switch (byteType)
  844.             {
  845.                     // special case single byte characters to allow lower case characters to map to
  846.                     // upper case characters
  847.                 case smSingleByte:
  848.                     areEqual = (LowerChar(first[1]) == LowerChar(second[1]));
  849.                     done = TRUE;
  850.                     break;
  851.  
  852.                 case smFirstByte:
  853.                     done = !areEqual;            // we're done if they don't match 
  854.                     break;
  855.  
  856.                 case smLastByte:
  857.                     done = TRUE;
  858.                     break;
  859.             }
  860.         } while (!done);
  861.     }
  862.  
  863.     return areEqual;
  864. }
  865.  
  866. //----------------------------------------------------------------------------------------
  867. // DefaultSize: 
  868. //----------------------------------------------------------------------------------------
  869. #pragma segment MAUtilitiesRes
  870.  
  871. void DefaultSize(short& theSize)
  872. {
  873.     if (theSize == GetDefFontSize())
  874.         theSize = 0;
  875. }
  876.  
  877. //----------------------------------------------------------------------------------------
  878. // DisposeIfPicHandle: 
  879. //----------------------------------------------------------------------------------------
  880. #pragma segment MAUtilitiesRes
  881.  
  882. PicHandle DisposeIfPicHandle(PicHandle aPicHandle)
  883. {
  884.     if (aPicHandle)
  885.     {
  886. #if !qDebug
  887.         KillPicture(aPicHandle);
  888. #else
  889.         char msg[128];
  890.  
  891.         if (IsHandle((Handle)aPicHandle))        // Test handlehood 
  892.         {
  893.             // Set the handle contents to a real nice value for any dangling pointerciples 
  894.             BlockSet(*((Handle)aPicHandle), GetHandleSize((Handle)aPicHandle), kDisposedInitVal);
  895.             KillPicture(aPicHandle);
  896.         }
  897.         else
  898.         {
  899.             VerboseIsHandle((Handle)aPicHandle);// Get the diagnosis printed 
  900.             sprintf(msg, "Trying to dispose an invalid PicHandle)\nBad PicHandle: %p\n", aPicHandle);
  901.             ProgramBreak(msg);
  902.         }
  903. #endif
  904.  
  905.     }
  906.  
  907.     return NULL;
  908. }
  909.  
  910. //----------------------------------------------------------------------------------------
  911. // DisposeIfRgnHandle: 
  912. //----------------------------------------------------------------------------------------
  913. #pragma segment MAUtilitiesRes
  914.  
  915. RgnHandle DisposeIfRgnHandle(RgnHandle aRgnHandle)
  916. {
  917.     if (aRgnHandle)
  918.     {
  919. #if !qDebug
  920.         DisposeRgn(aRgnHandle);
  921. #else
  922.         char msg[128];
  923.  
  924.         // Test handlehood 
  925.         if (IsHandle((Handle)aRgnHandle))
  926.         {
  927.             // Set the handle contents to a real nice value for any dangling pointerciples 
  928.             BlockSet(*((Handle)aRgnHandle), GetHandleSize((Handle)aRgnHandle), kDisposedInitVal);
  929.             DisposeRgn(aRgnHandle);
  930.         }
  931.         else
  932.         {
  933.             VerboseIsHandle((Handle)aRgnHandle);// Get the diagnosis printed 
  934.             sprintf(msg, "Trying to dispose an invalid RgnHandle.\nBad RgnHandle: %p\n", aRgnHandle);
  935.             ProgramBreak(msg);
  936.         }
  937. #endif
  938.  
  939.     }
  940.  
  941.     return NULL;
  942. }
  943.  
  944. //----------------------------------------------------------------------------------------
  945. // DisposeIfSectionHandle: 
  946. //----------------------------------------------------------------------------------------
  947. #pragma segment MAUtilitiesRes
  948.  
  949. SectionHandle DisposeIfSectionHandle(SectionHandle aSectionHandle)
  950. {
  951.     if (aSectionHandle)
  952.     {
  953. #if !qDebug
  954.         DisposeIfHandle((Handle)(*aSectionHandle)->alias);// dispose of the alias
  955.         DisposeIfHandle((Handle)aSectionHandle);// dispose of the SectionHandle
  956. #else
  957.         char msg[128];
  958.  
  959.         // Test handlehood 
  960.         if (IsHandle((Handle)aSectionHandle))
  961.         {
  962.             DisposeIfHandle((Handle)(*aSectionHandle)->alias);// dispose of the alias
  963.  
  964.             // Set the handle contents to a real nice value for any dangling pointerciples 
  965.             BlockSet(*((Handle)aSectionHandle), GetHandleSize((Handle)aSectionHandle), kDisposedInitVal);
  966.             DisposeIfHandle((Handle)aSectionHandle);// dispose of the SectionHandle
  967.         }
  968.         else
  969.         {
  970.             VerboseIsHandle((Handle)aSectionHandle);// Get the diagnosis printed 
  971.             sprintf(msg, "Trying to dispose an invalid SectionHandle.\nBad SectionHandle: %p\n", aSectionHandle);
  972.             ProgramBreak(msg);
  973.         }
  974. #endif
  975.  
  976.     }
  977.  
  978.     return NULL;
  979. }
  980.  
  981.  
  982. //----------------------------------------------------------------------------------------
  983. // FindWindowBefore: returns the window just before a given window. Returns NULL if the
  984. // given window is frontmost or not found.
  985. //----------------------------------------------------------------------------------------
  986. #pragma segment MAUtilitiesRes
  987.  
  988. WindowRef FindWindowBefore(WindowRef theWindow)
  989. {
  990.     WindowRef returnVal = NULL;
  991.  
  992.     CWMgrIterator iter;
  993.  
  994.     for (WindowRef theWMgrWindow = iter.FirstWMgrWindow(); iter.More(); theWMgrWindow = iter.NextWMgrWindow())
  995.     {
  996.         if (GetNextWindow(theWMgrWindow) == theWindow)
  997.         {
  998.             returnVal = theWMgrWindow;
  999.             break;
  1000.         }
  1001.     }
  1002.  
  1003.     return returnVal;
  1004. }
  1005.  
  1006. //----------------------------------------------------------------------------------------
  1007. // GetActualJustification: 
  1008. //----------------------------------------------------------------------------------------
  1009. #pragma segment MAUtilitiesRes
  1010.  
  1011. short GetActualJustification(short justification)
  1012. {
  1013.     return justification == teFlushDefault ? GetSysDirection() : justification;
  1014. }
  1015.  
  1016. //----------------------------------------------------------------------------------------
  1017. // GetDeskTopRegion: 
  1018. //----------------------------------------------------------------------------------------
  1019. #pragma segment MAUtilitiesRes
  1020.  
  1021. void GetDeskTopRegion(RgnHandle deskTopRgn)
  1022. {
  1023.     if (qNeedsColorQD || HasColorQD())            // deskTopRgn = main screen CRect 
  1024.         RectRgn(deskTopRgn, &((*GetMainDevice())->gdRect));
  1025.     else
  1026.         RectRgn(deskTopRgn, &(qd.screenBits.bounds));
  1027.     UnionRgn(GetGrayRgn(), deskTopRgn, deskTopRgn);// deskTopRgn = grayRgn + deskTopRgn 
  1028. }
  1029.  
  1030. //----------------------------------------------------------------------------------------
  1031. // ShowGlobalRegion: 
  1032. //----------------------------------------------------------------------------------------
  1033. #pragma segment MAUtilitiesRes
  1034.  
  1035. void ShowGlobalRegion(RgnHandle globalRegion)
  1036. {
  1037.     if (globalRegion)
  1038.     {
  1039.         GrafPtr savedPort;
  1040.         CGrafPort desktopPort;
  1041.         long ticks;
  1042.  
  1043.         // Cursor region is in global coords. Need to create desktop port 
  1044.         GetPort(&savedPort);
  1045.         if (qNeedsColorQD || HasColorQD())
  1046.             OpenCPort(&desktopPort);
  1047.         else
  1048.             OpenPort((GrafPtr) & desktopPort);
  1049.  
  1050.         CopyRgn(GetGrayRgn(), TWindow::GetVisRegion((GrafPtr) & desktopPort));
  1051.         desktopPort.portRect = (*TWindow::GetVisRegion((GrafPtr) & desktopPort))->rgnBBox;
  1052.  
  1053.         PenNormal();
  1054.         PenMode(patXor);
  1055.  
  1056.         PaintRgn(globalRegion);
  1057.         Delay(30, &ticks);
  1058.         PaintRgn(globalRegion);
  1059.  
  1060.         if (qNeedsColorQD || HasColorQD())
  1061.             CloseCPort(&desktopPort);
  1062.         else
  1063.             ClosePort((GrafPtr) & desktopPort);
  1064.         SetPort(savedPort);
  1065.     }
  1066. }
  1067.  
  1068. //----------------------------------------------------------------------------------------
  1069. // ShowViewRegion: 
  1070. //----------------------------------------------------------------------------------------
  1071. #pragma segment MAUtilitiesRes
  1072.  
  1073. void ShowViewRegion(TView* theView,
  1074.                     RgnHandle viewRegion)
  1075. {
  1076.     if (viewRegion && theView)
  1077.     {
  1078.         CTemporaryRegion tempRegion;
  1079.  
  1080.         CopyRgn(viewRegion, tempRegion);
  1081.         theView->LocalToGlobalRegion(tempRegion);
  1082.         ShowGlobalRegion(tempRegion);
  1083.     }
  1084. }
  1085.  
  1086. //----------------------------------------------------------------------------------------
  1087. // GetFontNum: 
  1088. //----------------------------------------------------------------------------------------
  1089. #pragma segment MAUtilitiesRes
  1090.  
  1091. short GetFontNum(const CStr255& fontName)
  1092. {
  1093.     short fontNum;
  1094.     CStr255 localFontName(fontName);
  1095.  
  1096.     UprStr255(localFontName);
  1097.     if (localFontName == CStr255(kSysFontName))
  1098.         fontNum = GetSysFont();
  1099.     else if (localFontName == CStr255(kApplFontName))
  1100.         fontNum = GetAppFont();
  1101.     else
  1102.         GetFNum(fontName, &fontNum);
  1103.  
  1104.     return fontNum;
  1105. }
  1106.  
  1107. //----------------------------------------------------------------------------------------
  1108. // GetIfBkColor: 
  1109. //----------------------------------------------------------------------------------------
  1110. #pragma segment MAUtilitiesRes
  1111.  
  1112. CRGBColor GetIfBkColor()
  1113. {
  1114.     // Since we require system 7 we can always use the GetFore/BackColor calls
  1115.     // because QD will do the color mapping for us
  1116.  
  1117.     CRGBColor aColor;
  1118.  
  1119.     GetBackColor(aColor);
  1120.     
  1121.     return aColor;
  1122. }
  1123.  
  1124. //----------------------------------------------------------------------------------------
  1125. // GetIfColor: 
  1126. //----------------------------------------------------------------------------------------
  1127. #pragma segment MAUtilitiesRes
  1128.  
  1129. CRGBColor GetIfColor()
  1130. {
  1131.     // Since we require system 7 we can always use the GetFore/BackColor calls
  1132.     // because QD will do the color mapping for us
  1133.  
  1134.     CRGBColor aColor;
  1135.  
  1136.     GetForeColor(aColor);
  1137.     
  1138.     return aColor;
  1139. }
  1140.  
  1141. //----------------------------------------------------------------------------------------
  1142. // MAGetFontInfo: 
  1143. //----------------------------------------------------------------------------------------
  1144. #pragma segment MAUtilitiesRes
  1145.  
  1146. short MAGetFontInfo(FontInfo& theFontInfo)
  1147. // MAGetFontInfo may be used in place of GetFontInfo since it also returns the font height. 
  1148. {
  1149.     GetFontInfo(&theFontInfo);                    // get the current port's font info 
  1150.     return (theFontInfo.ascent + theFontInfo.descent + theFontInfo.leading);// returns the font height 
  1151. }
  1152.  
  1153. //----------------------------------------------------------------------------------------
  1154. // GetPortFontInfo: 
  1155. //----------------------------------------------------------------------------------------
  1156. #pragma segment MAUtilitiesRes
  1157.  
  1158. void GetPortFontInfo(short fontNum,
  1159.                      CStr255& fontName,
  1160.                      short& fontSize)
  1161. {
  1162.     if ((fontNum == systemFont) || (fontNum == GetSysFont()))
  1163.     {
  1164.         fontName = kSysFontName;
  1165.         DefaultSize(fontSize);
  1166.     }
  1167.     else if ((fontNum == applFont) || (fontNum == GetAppFont()))
  1168.     {
  1169.         fontName = kApplFontName;
  1170.         DefaultSize(fontSize);
  1171.     }
  1172.     else
  1173.         GetFontName(fontNum, fontName);
  1174. }
  1175.  
  1176. //----------------------------------------------------------------------------------------
  1177. // GetRandom: 
  1178. //----------------------------------------------------------------------------------------
  1179. #pragma segment MAUtilitiesRes
  1180.  
  1181. long GetRandom(long rangeStart,
  1182.                long rangeEnd)
  1183. {
  1184.     unsigned short rndNum = Random();
  1185.     return (rangeStart < rangeEnd) ? rangeStart + rndNum % (rangeEnd - rangeStart + 1) : rangeStart;
  1186. }
  1187.  
  1188. //----------------------------------------------------------------------------------------
  1189. // IsColorPort: Returns true if the GrafPort is a Color QD GrafPort test is:
  1190. // IsColorPort = CGrafPtr(port)->portversion == 0xC000
  1191. //----------------------------------------------------------------------------------------
  1192. #pragma segment MAUtilitiesRes
  1193.  
  1194. Boolean IsColorPort(GrafPtr port)
  1195. {
  1196.     return port ? ((((CGrafPtr)port)->portVersion & (short)0xC000)) == (short)0xC000 : FALSE;
  1197. }
  1198.  
  1199. //----------------------------------------------------------------------------------------
  1200. // IsThisKeyDown: 
  1201. //----------------------------------------------------------------------------------------
  1202. #pragma segment MAUtilitiesRes
  1203.  
  1204. Boolean IsThisKeyDown(const short theKey)
  1205. {
  1206.     KeyMap map;
  1207.  
  1208.     GetKeys(map);
  1209.     return ((Byte *) & map)[theKey >> 3] & (1 << (theKey & 0x07)) ? TRUE : FALSE;
  1210. }
  1211.  
  1212. //----------------------------------------------------------------------------------------
  1213. // IsCapsLockKeyDown: 
  1214. //----------------------------------------------------------------------------------------
  1215. #pragma segment MAUtilitiesRes
  1216.  
  1217. Boolean IsCapsLockKeyDown()
  1218. {
  1219.     static const short kCapsLockKey = 57;
  1220.     return IsThisKeyDown(kCapsLockKey);
  1221. }
  1222.  
  1223. //----------------------------------------------------------------------------------------
  1224. // IsCommandKeyDown: 
  1225. //----------------------------------------------------------------------------------------
  1226. #pragma segment MAUtilitiesRes
  1227.  
  1228. Boolean IsCommandKeyDown()
  1229. {
  1230.     static const short kCommandKey = 55;
  1231.     return IsThisKeyDown(kCommandKey);
  1232. }
  1233.  
  1234. //----------------------------------------------------------------------------------------
  1235. // IsControlKeyDown: 
  1236. //----------------------------------------------------------------------------------------
  1237. #pragma segment MAUtilitiesRes
  1238.  
  1239. Boolean IsControlKeyDown()
  1240. {
  1241.     static const short kCtlKey = 0x3B;
  1242.     return IsThisKeyDown(kCtlKey);
  1243. }
  1244.  
  1245. //----------------------------------------------------------------------------------------
  1246. // IsOptionKeyDown: 
  1247. //----------------------------------------------------------------------------------------
  1248. #pragma segment MAUtilitiesRes
  1249.  
  1250. Boolean IsOptionKeyDown()
  1251. {
  1252.     static const short kOptionKey = 58;
  1253.     return IsThisKeyDown(kOptionKey);
  1254. }
  1255.  
  1256. //----------------------------------------------------------------------------------------
  1257. // IsShiftKeyDown: 
  1258. //----------------------------------------------------------------------------------------
  1259. #pragma segment MAUtilitiesRes
  1260.  
  1261. Boolean IsShiftKeyDown()
  1262. {
  1263.     static const short kShiftKey = 56;
  1264.     return IsThisKeyDown(kShiftKey);
  1265. }
  1266.  
  1267. //----------------------------------------------------------------------------------------
  1268. // LongerSide: 
  1269. //----------------------------------------------------------------------------------------
  1270. #pragma segment MAUtilitiesRes
  1271.  
  1272. VHSelect LongerSide(CRect& r)
  1273. {
  1274.     return r.GetLength(vSel) >= r.GetLength(hSel) ? vSel : hSel;
  1275. }
  1276.  
  1277. //----------------------------------------------------------------------------------------
  1278. // LongerVSide: 
  1279. //----------------------------------------------------------------------------------------
  1280. #pragma segment MAUtilitiesRes
  1281.  
  1282. VHSelect LongerVSide(VRect& r)
  1283. {
  1284.     return r.GetLength(vSel) >= r.GetLength(hSel) ? vSel : hSel;
  1285. }
  1286.  
  1287. //----------------------------------------------------------------------------------------
  1288. // LIntToHex: 
  1289. //----------------------------------------------------------------------------------------
  1290. #pragma segment MADebug
  1291.  
  1292. void LIntToHex(long decNumber,
  1293.                CStr31& hexNumber,
  1294.                short noOfDigits)
  1295. {
  1296.     short localNoOfDigits = (short)Min(noOfDigits, 8);
  1297.     long localDecNumber = decNumber;
  1298.     hexNumber[0] = (char)localNoOfDigits;
  1299.     for (short i = localNoOfDigits; i >= 1; i--, localDecNumber = localDecNumber >> 4)
  1300.         hexNumber[i] = kHexDigits[(localDecNumber & 15)];
  1301. }
  1302.  
  1303. //----------------------------------------------------------------------------------------
  1304. // NumberToHex: 
  1305. //----------------------------------------------------------------------------------------
  1306. #pragma segment MADebug
  1307.  
  1308. void NumberToHex(long theNumber,
  1309.                  CStr255& hexString,
  1310.                  short hexDigits)
  1311. {
  1312.     CStr31 tempString;
  1313.  
  1314.     LIntToHex(theNumber, tempString, hexDigits);
  1315.     hexString = "$" + tempString;
  1316. }
  1317.  
  1318. //----------------------------------------------------------------------------------------
  1319. // PointerToHex: 
  1320. //----------------------------------------------------------------------------------------
  1321. #pragma segment MADebug
  1322.  
  1323. void PointerToHex(long theNumber,
  1324.                   CStr31& hexString,
  1325.                   short hexDigits)
  1326. {
  1327.     CStr31 tempString;
  1328.  
  1329.     if (theNumber == 0)
  1330.         hexString = "NULL";
  1331.     else
  1332.     {
  1333.         LIntToHex(theNumber, tempString, hexDigits);
  1334.         hexString = "$" + tempString;
  1335.     }
  1336. }
  1337.  
  1338. //----------------------------------------------------------------------------------------
  1339. // NumBlocks: 
  1340. //----------------------------------------------------------------------------------------
  1341. #pragma segment MAFile
  1342.  
  1343. long NumBlocks(long numBytes,
  1344.                long blkSize)
  1345. {
  1346.     return (numBytes + blkSize - 1) / blkSize;
  1347. }
  1348.  
  1349.  
  1350. static Handle pSaveHText;
  1351. static Handle pMATextBoxHText;
  1352.  
  1353. //----------------------------------------------------------------------------------------
  1354. // StdNoRect: StdNoRect filters out the CRect drawing calls.
  1355. //----------------------------------------------------------------------------------------
  1356. #pragma segment MAUtilitiesRes
  1357.  
  1358. pascal void StdNoRect(GrafVerb                    /* verb */,
  1359.                       const CRect&                /* r */ )
  1360. {
  1361. }
  1362.  
  1363. //----------------------------------------------------------------------------------------
  1364. // InitMyPrivateTE: 
  1365. //----------------------------------------------------------------------------------------
  1366. void InitMyPrivateTE(const CRect& box,
  1367.                      short heapSize)
  1368. {
  1369.     static const short kZoneHeaderTrailer = 256;// 256 bytes for header and trailer
  1370.     static const short kMPBlockHeader = 32;        // 32 bytes for Master Pointer block hdr 
  1371.     static const short kInitialMstrPtrs = 2;    // 2 master pointers created initially 
  1372.     static const short kSlop = 32;                // bytes of slop (just in case) 
  1373.     static const short kZoneOverhead = kZoneHeaderTrailer + kMPBlockHeader + 4 * kInitialMstrPtrs + kSlop;// how large the zone overhead is 
  1374.     Ptr aTEZonePtr;
  1375.  
  1376.     gMATextBoxTE = TENew(box, box);
  1377.     if (gMATextBoxTE)                            // can allocate space for our terecord 
  1378.     {
  1379.         // • save off several items of interest
  1380.         gTEDefaultWordBreak = (*gMATextBoxTE)->wordBreak;
  1381.         pSaveHText = (*gMATextBoxTE)->hText;    // save the text handle 
  1382.  
  1383.         // Since TESetText (called near the end of MATextBox) hits the heap, we can speed this
  1384.         // hit to the heap for small text lengths (<= 255), by allocating a special text
  1385.         // handle in its own separate heap. We'll use this text handle whenever the text
  1386.         // length is <= 255.
  1387.  
  1388.         // • create a separate heap
  1389.         aTEZonePtr = NewPtr(((heapSize + 7) & ~7) + kZoneOverhead);
  1390.         if (aTEZonePtr)                            // can allocate space for our heap 
  1391.         {
  1392.             InitZone(NULL, kInitialMstrPtrs, aTEZonePtr + GetPtrSize(aTEZonePtr), aTEZonePtr);
  1393.  
  1394.             // • InitZone sets the current zone to the newly created zone
  1395.  
  1396.             // • allocate our new text handle in our new heap zone
  1397.             pMATextBoxHText = NewHandle(heapSize);// the text handle 
  1398.  
  1399.             // • restore the heap zone
  1400.             SetZone(ApplicationZone());
  1401.         }
  1402.     }
  1403. }
  1404.  
  1405.  
  1406. //----------------------------------------------------------------------------------------
  1407. // MATextBox: 
  1408. //----------------------------------------------------------------------------------------
  1409. void MATextBox(Ptr text,
  1410.                long itsLength,
  1411.                const CRect& box,
  1412.                short itsJust,
  1413.                Boolean autoWrap,
  1414.                ProcPtr wordBreak,
  1415.                Boolean eraseFirst,
  1416.                Boolean spaceForCaret,
  1417.                Boolean preferOutline)
  1418. {
  1419.     union QuickDrawProcs
  1420.     {
  1421.         QDProcs theQDProcs;
  1422.         CQDProcs theCQDProcs;
  1423.     };
  1424.  
  1425.  
  1426.     static const short kTextBoxCaretSlopSize = 1;// Since TETextBox uses TE to image the
  1427.     // text, we may need to adjust by 1 pixel.
  1428.     // Reason: TE draws beginning 1 pixel to
  1429.     // the right to allow for the insertion
  1430.     // point (which we won't have since this
  1431.     // is drawn text, not editable text).
  1432.     static const short kMaxTEChars = 32000;        // Actually TE suffers some other
  1433.     // limitations as well. Such as
  1434.     // misbehaviour and or bombing when the
  1435.     // sum of the lineheights > 32k or a
  1436.     // linewidth > 32k (overflows QuickDraw
  1437.     // space) But these are _MUCH_ more
  1438.     // difficult to test for in a quick way
  1439.     static const short kOurHeapSize = 256;        // our zone size 
  1440.  
  1441.     QuickDrawProcs myQDProcs;
  1442.     QDProcsPtr saveQDProcsPtr;
  1443.     WordBreakUPP wbUPP = NULL;
  1444.     QDRectUPP saveRectProc;
  1445.  
  1446.     CWhileOutlinePreferred setOP(preferOutline);
  1447.  
  1448.     // Create my goodies if necessary 
  1449.     if (gMATextBoxTE == NULL)
  1450.     {
  1451.         InitMyPrivateTE(box, kOurHeapSize);
  1452.  
  1453.         if (gMATextBoxTE == NULL)                // couldn't allocate the TE handle 
  1454.         {
  1455.             TETextBox(text, itsLength, box, itsJust);// default to TextBox in low memory 
  1456.             return;
  1457.         }
  1458.     }
  1459.  
  1460.     // Setup the work TE with the necessary parameters 
  1461.     FontInfo fInfo;
  1462.     short lineHeight = MAGetFontInfo(fInfo);    // Need to get font's height and ascent. 
  1463.  
  1464.     TERec & workTE = **gMATextBoxTE;
  1465.  
  1466.     // Intersect the clip and the requested box
  1467.     ((CRect &)workTE.viewRect) = ((CRect &)(*TView::GetClipRegion(qd.thePort))->rgnBBox) & box;
  1468.     ((CRect &)workTE.destRect) = box;
  1469.     if (!spaceForCaret)
  1470.     {
  1471.         // Widen the destrect but not the visrect. This lets the 1 pixel wide area to the
  1472.         // left of all text and the right of all text go unshown.
  1473.         workTE.destRect.left -= kTextBoxCaretSlopSize;
  1474.         workTE.destRect.right += kTextBoxCaretSlopSize;
  1475.     }
  1476.  
  1477.     workTE.inPort = qd.thePort;                    // Current port and its characteristics 
  1478.  
  1479.     workTE.txSize = qd.thePort->txSize;
  1480.     workTE.txFont = qd.thePort->txFont;
  1481.     workTE.txFace = qd.thePort->txFace;
  1482.     workTE.fontAscent = fInfo.ascent;
  1483.     workTE.lineHeight = lineHeight;
  1484.     workTE.just = itsJust;
  1485.  
  1486.     if (autoWrap)
  1487.         workTE.crOnly = 0;                        //if >=0, word wrap
  1488.     else
  1489.         workTE.crOnly = -1;                        //if <0, new line at Return only
  1490.  
  1491.     workTE.wordBreak = gTEDefaultWordBreak;
  1492.  
  1493.     if (wordBreak != NULL)
  1494.     {
  1495.         FailNIL(wbUPP = NewWordBreakProc(wordBreak));
  1496.         workTE = **gMATextBoxTE;                // re-dereference because memory may have moved
  1497.         workTE.wordBreak = wbUPP;
  1498.     }
  1499.  
  1500.     if (pMATextBoxHText != NULL)                // if our private heap is set up 
  1501.     {
  1502.         if (itsLength > kOurHeapSize)
  1503.             workTE.hText = pSaveHText;
  1504.         else
  1505.             workTE.hText = pMATextBoxHText;
  1506.     }
  1507.  
  1508.     TESetText(text, Min(itsLength, kMaxTEChars), gMATextBoxTE);
  1509.  
  1510.     // if called with eraseFirst true, then let TEUpdate image with its built-in EraseRect 
  1511.     if (eraseFirst)
  1512.         TEUpdate(box, gMATextBoxTE);
  1513.     else
  1514.     {
  1515.         /* replace the existing QD procs ( standard or externally supplied )
  1516.           so that the EraseRect in TEUpdate is ignored */
  1517.         saveQDProcsPtr = qd.thePort->grafProcs;
  1518.  
  1519.         QDRectUPP theRectProc = NewQDRectProc(&StdNoRect);
  1520.         FailNIL(theRectProc);
  1521.  
  1522.         if (saveQDProcsPtr == NULL)
  1523.         {
  1524.             if (IsColorPort(qd.thePort))
  1525.             {
  1526.                 SetStdCProcs(&(myQDProcs.theCQDProcs));
  1527.                 myQDProcs.theCQDProcs.rectProc = theRectProc;
  1528.                 qd.thePort->grafProcs = (QDProcsPtr) & myQDProcs.theCQDProcs;
  1529.             }
  1530.             else
  1531.             {
  1532.                 SetStdProcs(&(myQDProcs.theQDProcs));
  1533.                 myQDProcs.theQDProcs.rectProc = theRectProc;
  1534.                 qd.thePort->grafProcs = &myQDProcs.theQDProcs;
  1535.             }
  1536.         }
  1537.         else
  1538.         {
  1539.             saveRectProc = qd.thePort->grafProcs->rectProc;
  1540.             qd.thePort->grafProcs->rectProc = theRectProc;
  1541.         }
  1542.  
  1543.         // Now do the imaging 
  1544.         TEUpdate(box, gMATextBoxTE);
  1545.  
  1546.         // Restore the QDProcs 
  1547.         if (saveQDProcsPtr == NULL)
  1548.             qd.thePort->grafProcs = NULL;
  1549.         else
  1550.             qd.thePort->grafProcs->rectProc = saveRectProc;
  1551.  
  1552.         theRectProc = (QDRectUPP)DisposeIfRoutineDescriptor((UniversalProcPtr)theRectProc);
  1553.     }
  1554.  
  1555.     if (wbUPP)
  1556.     {
  1557.         DisposeRoutineDescriptor(wbUPP);
  1558.         wbUPP = NULL;
  1559.     }
  1560. }
  1561.  
  1562. //----------------------------------------------------------------------------------------
  1563. // MADrawString: 
  1564. //----------------------------------------------------------------------------------------
  1565. #pragma segment MAUtilitiesRes
  1566.  
  1567. void MADrawString(const CStr255& s,
  1568.                   const CRect& box,
  1569.                   short justification,
  1570.                   Boolean preferOutline)
  1571. {
  1572.     FontInfo theFontInfo;
  1573.     short widthOfString;
  1574.     short boxWidth;
  1575.     CRect localBox = box;
  1576.  
  1577.     CWhileOutlinePreferred setOP(preferOutline);
  1578.  
  1579.     GetFontInfo(&theFontInfo);
  1580.     widthOfString = StringWidth(s);
  1581.     boxWidth = localBox.GetLength(hSel);
  1582.     if (widthOfString < boxWidth)
  1583.     {
  1584.         switch (GetActualJustification(justification))
  1585.         {
  1586.             case teFlushDefault:
  1587.                 break;
  1588.  
  1589.             case teCenter:
  1590.                 localBox.left += (boxWidth - widthOfString) / 2;
  1591.                 break;
  1592.  
  1593.             case teFlushRight:
  1594.                 localBox.left += boxWidth - widthOfString;
  1595.                 break;
  1596.  
  1597.             case teFlushLeft:
  1598.                 break;
  1599.         }
  1600.     }
  1601.  
  1602.     MoveTo(localBox.left, localBox.top + theFontInfo.ascent);
  1603.     DrawString(s);
  1604. }
  1605.  
  1606. //----------------------------------------------------------------------------------------
  1607. // PinOnRect: 
  1608. //----------------------------------------------------------------------------------------
  1609. #pragma segment MAUtilitiesRes
  1610.  
  1611. long PinOnRect(const CRect& theRect,
  1612.                CPoint thePt)
  1613. {
  1614.     CPoint localPt = thePt;
  1615.     if (localPt.h < theRect.left)
  1616.         localPt.h = theRect.left;
  1617.     if (localPt.h > theRect.right)
  1618.         localPt.h = theRect.right;
  1619.     if (localPt.v < theRect.top)
  1620.         localPt.v = theRect.top;
  1621.     if (localPt.v > theRect.bottom)
  1622.         localPt.v = theRect.bottom;
  1623.  
  1624.     return *((long*) & localPt);
  1625. }
  1626.  
  1627. //----------------------------------------------------------------------------------------
  1628. // PinOnVRect: 
  1629. //----------------------------------------------------------------------------------------
  1630. #pragma segment MAUtilitiesRes
  1631.  
  1632. void PinOnVRect(const VRect& theRect,
  1633.                 const VPoint& thePt,
  1634.                 VPoint& thePin)
  1635. {
  1636.     long hCoord = MinMax(theRect.left, thePt.h, theRect.right);
  1637.     long vCoord = MinMax(theRect.top, thePt.v, theRect.bottom);
  1638.     thePin = VPoint(hCoord, vCoord);
  1639. }
  1640.  
  1641. //----------------------------------------------------------------------------------------
  1642. // RoundUp: 
  1643. //----------------------------------------------------------------------------------------
  1644. #pragma segment MAUtilitiesRes
  1645.  
  1646. long RoundUp(long aNumber,
  1647.              short aModulus)
  1648. {
  1649.     return ((aNumber + aModulus - 1) / aModulus) * aModulus;
  1650. }
  1651.  
  1652. //----------------------------------------------------------------------------------------
  1653. // SetKeyScript: 
  1654. //----------------------------------------------------------------------------------------
  1655. #pragma segment MAUtilitiesRes
  1656.  
  1657. short SetKeyScript(short newKeyScript)
  1658. {
  1659.     short currentKeyScript = (short)GetScriptManagerVariable(smKeyScript);
  1660.     if (currentKeyScript != newKeyScript)        // Don't unnecessarily annoy the script mgr 
  1661.         KeyScript(newKeyScript);
  1662.     return currentKeyScript;
  1663. }
  1664.  
  1665. //----------------------------------------------------------------------------------------
  1666. // SetIfBkColor: 
  1667. //----------------------------------------------------------------------------------------
  1668. #pragma segment MAUtilitiesRes
  1669.  
  1670. void SetIfBkColor(const CRGBColor& aColor)
  1671. {
  1672.     // Since we require system 7 we can always use the RGBFore/BackColor calls
  1673.     // because QD will do the color mapping for us
  1674.  
  1675.     // Try to avoid calling RGBFore/BackColor unnecessarally
  1676.     if (!IsColorPort(qd.thePort) || (((CRGBColor &) ((CGrafPtr) qd.thePort)->rgbBkColor) != aColor))
  1677.         RGBBackColor(aColor);
  1678. }
  1679.  
  1680. //----------------------------------------------------------------------------------------
  1681. // SetIfColor: 
  1682. //----------------------------------------------------------------------------------------
  1683. #pragma segment MAUtilitiesRes
  1684.  
  1685. void SetIfColor(const CRGBColor& aColor)
  1686. {
  1687.     // Since we require system 7 we can always use the RGBFore/BackColor calls
  1688.     // because QD will do the color mapping for us
  1689.  
  1690.     // Try to avoid calling RGBFore/BackColor unnecessarally
  1691.     if (!IsColorPort(qd.thePort) || (((CRGBColor &) ((CGrafPtr) qd.thePort)->rgbFgColor) != aColor))
  1692.         RGBForeColor(aColor);
  1693. }
  1694.  
  1695. //----------------------------------------------------------------------------------------
  1696. // GetPortTextStyle: 
  1697. //----------------------------------------------------------------------------------------
  1698. #pragma segment MAUtilitiesRes
  1699.  
  1700. void GetPortTextStyle(TextStyle& theTextStyle)
  1701. {
  1702.     theTextStyle.tsFont = qd.thePort->txFont;
  1703.     theTextStyle.tsFace = qd.thePort->txFace;
  1704.     theTextStyle.tsSize = qd.thePort->txSize;
  1705.     theTextStyle.tsColor = GetIfColor();
  1706. }
  1707.  
  1708. //----------------------------------------------------------------------------------------
  1709. // MAGetTextStyle: 
  1710. //----------------------------------------------------------------------------------------
  1711. #pragma segment MAUtilitiesRes
  1712.  
  1713. void MAGetTextStyle(ResNumber rsrcID,
  1714.                     TextStyle& theTextStyle)
  1715. {
  1716.     MATextStyleHandle theTextStyleHdl = (MATextStyleHandle)GetResource('TxSt', rsrcID);
  1717.     FailNILResource((Handle)theTextStyleHdl);
  1718.  
  1719.     MATextStyle & resourceStyle = **theTextStyleHdl;
  1720.  
  1721.     theTextStyle.tsFace = resourceStyle.tsFace;
  1722.     theTextStyle.tsSize = resourceStyle.tsSize;
  1723.     theTextStyle.tsColor = *((RGBColor *) & (resourceStyle.tsColor));
  1724.  
  1725.     CStr255 itsFont((*theTextStyleHdl)->tsFont);
  1726.     theTextStyle.tsFont = GetFontNum(itsFont);
  1727. }
  1728.  
  1729. //----------------------------------------------------------------------------------------
  1730. // SetPortTextStyle: 
  1731. //----------------------------------------------------------------------------------------
  1732. #pragma segment MAUtilitiesRes
  1733.  
  1734. void SetPortTextStyle(const TextStyle& theTextStyle)
  1735. {
  1736.     if (qd.thePort->txFont != theTextStyle.tsFont)
  1737.         TextFont(theTextStyle.tsFont);
  1738.     if (qd.thePort->txFace != theTextStyle.tsFace)
  1739.         TextFace(theTextStyle.tsFace);
  1740.     if (qd.thePort->txSize != theTextStyle.tsSize)
  1741.         TextSize(theTextStyle.tsSize);
  1742.     SetIfColor(theTextStyle.tsColor);
  1743. }
  1744.  
  1745. //----------------------------------------------------------------------------------------
  1746. // SetTextStyle: 
  1747. //----------------------------------------------------------------------------------------
  1748. #pragma segment MAUtilitiesRes
  1749.  
  1750. void SetTextStyle(TextStyle& theTextStyle,
  1751.                   short theFont,
  1752.                   /* Style */
  1753.                   short theStyle,
  1754.                   short theSize,
  1755.                   const CRGBColor& theColor)
  1756. {
  1757.     theTextStyle.tsFont = theFont;
  1758.     theTextStyle.tsFace = theStyle;
  1759.     theTextStyle.tsSize = theSize;
  1760.     theTextStyle.tsColor = theColor;
  1761. }
  1762.  
  1763. //----------------------------------------------------------------------------------------
  1764. // UseSelectionColor: 
  1765. //----------------------------------------------------------------------------------------
  1766. #pragma segment MAUtilitiesRes
  1767.  
  1768. void UseSelectionColor()
  1769. {
  1770.     unsigned char hiliteModeValue = LMGetHiliteMode();
  1771.     BitClr((Ptr) & hiliteModeValue, pHiliteBit);
  1772.     LMSetHiliteMode(hiliteModeValue);
  1773. }
  1774.  
  1775. //----------------------------------------------------------------------------------------
  1776. // CheckAdornment: 
  1777. //----------------------------------------------------------------------------------------
  1778. #pragma segment MADebug2
  1779.  
  1780. void CheckAdornment(CntlAdornment p,
  1781.                     CntlAdornment alias,
  1782.                     CStr255 theString,
  1783.                     char* name)
  1784. {
  1785.     // "set1 <= set2" means set1 is wholly contained in set2 
  1786.     if (p <= alias)
  1787.         if (theString == CStr255("["))
  1788.             theString = theString + name;
  1789.         else
  1790.             theString = theString + CStr255(",") + name;
  1791. }
  1792.  
  1793.  
  1794. //----------------------------------------------------------------------------------------
  1795. // CheckStyleItem: 
  1796. //----------------------------------------------------------------------------------------
  1797. void CheckStyleItem(unsigned char s,
  1798.                     unsigned char alias,
  1799.                     CStr255 theString,
  1800.                     char* name)
  1801. {
  1802.     if (s & alias)
  1803.         if (theString == CStr255("["))
  1804.             theString = theString + name;
  1805.         else
  1806.             theString = theString + CStr255(",") + name;
  1807. }
  1808.  
  1809. //----------------------------------------------------------------------------------------
  1810. // RotatePat: 
  1811. //----------------------------------------------------------------------------------------
  1812. #pragma segment MAUtilitiesRes
  1813. void RotatePat(Pattern& aPattern)
  1814. {
  1815.     unsigned char temp = aPattern.pat[0];
  1816.     for (short index = 0; index < (sizeof(Pattern) - 1); index++)
  1817.         aPattern.pat[index] = aPattern.pat[index + 1];
  1818.     aPattern.pat[sizeof(Pattern) - 1] = temp;
  1819. }
  1820.  
  1821. //----------------------------------------------------------------------------------------
  1822. // XorPat: 
  1823. //----------------------------------------------------------------------------------------
  1824. #pragma segment MAUtilitiesRes
  1825. void XorPat(const Pattern& patA,
  1826.             const Pattern& patB,
  1827.             Pattern& toPat)
  1828. {
  1829.     for (short index = 0; index < sizeof(Pattern); index++)
  1830.         toPat.pat[index] = patA.pat[index] ^ patB.pat[index];// xor
  1831. }
  1832.  
  1833. //----------------------------------------------------------------------------------------
  1834. // StreamToHandle: 
  1835. //----------------------------------------------------------------------------------------
  1836. #pragma segment MAUtilitiesRes
  1837.  
  1838. Handle StreamToHandle(TStream* theStream)
  1839. {
  1840.     MAVolatileInit(Handle, dataHandle, NULL);
  1841.     Size dataSize = theStream->GetSize() - theStream->GetPosition();
  1842.  
  1843.     FailInfo fi;
  1844.     Try(fi)
  1845.     {
  1846.         dataHandle = NewPermHandle(dataSize);    // fails if error
  1847.  
  1848.         HLock(dataHandle);
  1849.         theStream->ReadBytes(*dataHandle, dataSize);
  1850.         HUnlock(dataHandle);
  1851.         fi.Success();
  1852.     }
  1853.     else // Recover
  1854.     {
  1855.         dataHandle = DisposeIfHandle(dataHandle);
  1856.     }
  1857.  
  1858.     return dataHandle;
  1859. }
  1860.  
  1861. //----------------------------------------------------------------------------------------
  1862. // End of UMacAppUtilities.cp
  1863.  
  1864. #pragma segment Inline
  1865.  
  1866.